#!/bin/bash
set -euo pipefail

# 初始化配置参数
DOCKER_VERSION="24.0.1"
MIRROR_URL="https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo"
IMAGE_LIST=(
    "mysql:8.0-debian"
    "nginx:1.25-alpine"
    "openjdk:17-slim"
    "redis:7.0-alpine"
    "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/ghcr.io/chevereto/chevereto:latest"
)
# 特殊处理的镜像与备用镜像
SPECIAL_IMAGES=(
    "nmtan/chevereto:latest|registry.cn-hangzhou.aliyuncs.com/rodolfo/chevereto:latest|registry.cn-beijing.aliyuncs.com/xuxiaowei-com/chevereto:latest"
)
DIRECTORIES=(
    "/root/mysql" 
    "/root/mysql/conf.d"
    "/root/nginx" 
    "/root/nginx/conf" 
    "/root/nginx/cert" 
    "/root/nginx/log" 
    "/root/nginx/cache" 
    "/root/nginx/html"
    "/root/nginx/uniapp"
    "/root/asj-server"
    "/root/asj-server/jar"
    "/root/asj-server/config"
    "/root/asj-server/logs"
    "/root/chevereto"
    "/root/chevereto/app"
    "/root/chevereto/images"
    "/root/secrets"
)
SECRET_DIRS="/root/secrets"
LOG_FILE="/var/log/server-init-$(date +%Y%m%d%H%M%S).log"
MAX_RETRIES=3
RETRY_DELAY=5

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志记录函数
log() {
    echo -e "$(date "+%Y-%m-%d %T") $*" | tee -a "$LOG_FILE"
}

# 错误处理函数
error_exit() {
    log "${RED}[ERROR] $* ${NC}"
    exit 1
}

# 警告函数
warn() {
    log "${YELLOW}[WARNING] $* ${NC}"
}

# 信息函数
info() {
    log "${BLUE}[INFO] $* ${NC}"
}

# 验证root权限
[[ $EUID -ne 0 ]] && error_exit "必须以root用户运行此脚本"

# 设置Docker拉取超时
export DOCKER_CLIENT_TIMEOUT=300
export COMPOSE_HTTP_TIMEOUT=300

# 安装基础依赖
log "${GREEN}[1/10] 安装系统依赖...${NC}"
yum install -y yum-utils curl device-mapper-persistent-data lvm2 || error_exit "依赖安装失败"

# 配置镜像源
log "${GREEN}[2/10] 配置镜像源...${NC}"
if ! curl -fsSL $MIRROR_URL -o /etc/yum.repos.d/docker-ce.repo; then
    error_exit "镜像源配置失败"
fi
yum-config-manager --add-repo $MIRROR_URL || error_exit "仓库添加失败"

# Docker安装
log "${GREEN}[3/10] 安装Docker...${NC}"
yum install -y docker-ce-$DOCKER_VERSION docker-ce-cli-$DOCKER_VERSION containerd.io docker-compose-plugin || error_exit "Docker安装失败"

# Docker配置
log "${GREEN}[4/10] 配置Docker...${NC}"
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << EOF
{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": true,
  "features": {
    "buildkit": true
  },
  "insecure-registries": ["172.24.86.231"],
  "registry-mirrors": [
    "https://registry.docker-cn.com",
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com",
    "https://dockerproxy.com",
    "https://docker.m.daocloud.io",
    "https://docker.nju.edu.cn"
  ],
  "log-driver":"json-file",
  "log-opts": {
    "max-size":"500m",
    "max-file":"3"
  }
}
EOF

# 启动Docker服务
log "${GREEN}[5/10] 启动Docker服务...${NC}"
systemctl daemon-reload || error_exit "服务重载失败"
systemctl enable docker && systemctl restart docker || error_exit "Docker启动失败"
# 等待Docker服务完全启动
sleep 5

# 验证Docker安装
if ! docker info &>/dev/null; then
    error_exit "Docker服务验证失败"
fi

# 镜像拉取与处理
log "${GREEN}[6/10] 拉取基础镜像...${NC}"
declare -A RENAMED_IMAGES

# 拉取镜像
for image in "${IMAGE_LIST[@]}"; do
    log "正在拉取 $image..."
    
    success=false
    for ((retry=1; retry<=$MAX_RETRIES; retry++)); do
        if docker pull "$image"; then
            success=true
            info "$image 拉取成功"
            
            # 如果是华为云的Chevereto镜像，记录需要重命名
            if [[ "$image" == *"huaweicloud"*"chevereto"* ]]; then
                RENAMED_IMAGES["$image"]="nmtan/chevereto:latest"
            fi
            break
        else
            if [ $retry -lt $MAX_RETRIES ]; then
                warn "拉取 $image 失败，${retry}/${MAX_RETRIES} 次尝试，等待 ${RETRY_DELAY} 秒后重试..."
                sleep $RETRY_DELAY
            fi
        fi
    done
    
    if ! $success; then
        warn "$image 拉取失败 $MAX_RETRIES 次，跳过此镜像"
    fi
done

# 创建目录结构
log "${GREEN}[7/10] 创建目录...${NC}"
for dir in "${DIRECTORIES[@]}"; do
    mkdir -p "$dir" || error_exit "$dir 创建失败"
    chmod -R 755 "$dir" || error_exit "$dir 权限设置失败"
done

# 设置日志和数据目录的特殊权限
log "设置日志和数据目录权限..."
chmod -R 777 "/root/nginx/log" "/root/nginx/cache" "/root/asj-server/logs" "/root/chevereto/images" || warn "日志目录权限设置可能不完全"

# 创建和验证密钥文件
log "${GREEN}[8/10] 设置密钥...${NC}"
mkdir -p "$SECRET_DIRS"
chmod 700 "$SECRET_DIRS" # 仅root可访问密钥目录

# 检查必要的密钥文件
SECRET_FILES=("mysql_root.txt" "chevereto_db.txt" "redis_password.txt")
for secret in "${SECRET_FILES[@]}"; do
    secret_path="$SECRET_DIRS/$secret"
    if [[ ! -f "$secret_path" ]]; then
        # 生成随机密码
        case "$secret" in
            "mysql_root.txt")
                openssl rand -base64 16 > "$secret_path"
                log "已创建MySQL root密码"
                ;;
            "chevereto_db.txt")
                openssl rand -base64 12 > "$secret_path"
                log "已创建Chevereto数据库密码"
                ;;
            "redis_password.txt")
                openssl rand -base64 16 > "$secret_path"
                log "已创建Redis密码"
                ;;
        esac
    else
        log "密钥文件 $secret 已存在"
    fi
    # 设置权限
    chmod 600 "$secret_path" || error_exit "无法设置 $secret_path 的权限"
done

# 创建Docker网络
log "${GREEN}[9/10] 创建网络...${NC}"
if ! docker network ls | grep -q net-gold; then
    docker network create -d bridge --subnet 172.28.0.0/24 net-gold || error_exit "网络创建失败"
else
    log "网络 net-gold 已存在"
fi

# 镜像重命名和清理
log "${GREEN}[10/10] 镜像重命名和清理...${NC}"
# 创建软链接到当前目录
ln -sf "$SECRET_DIRS" ./secrets || warn "创建secrets软链接失败"

# 重命名镜像并删除原始镜像
for orig_image in "${!RENAMED_IMAGES[@]}"; do
    new_name="${RENAMED_IMAGES[$orig_image]}"
    if docker images --format "{{.Repository}}:{{.Tag}}" | grep -q "$orig_image"; then
        info "将 $orig_image 重命名为 $new_name"
        docker tag "$orig_image" "$new_name" && \
        docker rmi "$orig_image" && \
        info "重命名完成并删除原始镜像" || \
        warn "重命名或删除 $orig_image 失败"
    fi
done

# 清理未使用的镜像和缓存
info "清理未使用的镜像和构建缓存..."
docker image prune -f

# 创建.env文件
log "创建.env环境变量文件..."
cat > ./.env << EOF
# 数据库设置
MYSQL_DATABASE=goldweb
MYSQL_USER=root
# 图片服务设置
CHEVERETO_DB_NAME=chevereto
CHEVERETO_DB_USER=gold
# Redis设置
REDIS_PASSWORD=$(cat "$SECRET_DIRS/redis_password.txt")
EOF

# 更新docker-compose.yml中的secrets路径
if [ -f "./docker-compose.yml" ]; then
    info "更新docker-compose.yml中的secrets路径..."
    sed -i 's|file: ./secrets/|file: /root/secrets/|g' ./docker-compose.yml || \
    warn "无法更新docker-compose.yml中的secrets路径"
fi

# 最终验证
log "${GREEN}验证关键组件...${NC}"

# 检查镜像是否全部成功
missing_images=false
for image in "mysql:8.0-debian" "nginx:1.25-alpine" "openjdk:17-slim" "redis:7.0-alpine" "nmtan/chevereto:latest"; do
    if ! docker images --format "{{.Repository}}:{{.Tag}}" | grep -q "$image"; then
        warn "镜像 $image 不存在"
        missing_images=true
    fi
done

if $missing_images; then
    warn "部分镜像可能未成功拉取，请检查后手动处理"
else
    info "所有镜像已成功准备"
fi

# 检查网络
docker network ls | grep -q net-gold || error_exit "网络验证失败"

log "${GREEN}服务器初始化完成! 详细日志见: $LOG_FILE ${NC}"
log "${GREEN}启动服务可使用: docker compose up -d${NC}"